package com.yj.core.util;


import com.yj.core.exception.ServiceException;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.FastDateFormat;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

public class DateUtil {

    /**
     * postgresql dateTime 支持的时间的最大值.
     */
    public static final Date DATE_POSITIVE_INFINITY = new Date(9223372036825200000L);
    /**
     * postgresql dateTime 支持的时间的最小值.
     */
    public static final Date DATE_NEGATIVE_INFINITY = new Date(-9223372036825200000L);

    private static final FastDateFormat DATE_FORMATTER = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss");
    private static final FastDateFormat BASE_DATE_FORMATTER = FastDateFormat.getInstance("yyyy-MM-dd");
    private static final FastDateFormat BASE_DATE_FORMATTER_1 = FastDateFormat.getInstance("yyyyMMdd");
    private static final FastDateFormat MONTH_FORMATTER = FastDateFormat.getInstance("yyyy-MM");
    private static final FastDateFormat GAPLESS_DATE_FORMATTER = FastDateFormat.getInstance("yyyyMMddHHmmss");

    private static final FastDateFormat MILLIS_DATE_FORMATTER = FastDateFormat.getInstance("yyyyMMddHHmmssS");
    private static final FastDateFormat HOUR_MINUTE_DATE_FORMATTER = FastDateFormat.getInstance("HH:mm");
    private static final FastDateFormat HOUR_MINUTE_FORMATTER = FastDateFormat.getInstance("yyyy-MM-dd HH:mm");

    private static final int[] SEASON_1 = {0, 1, 2};
    private static final int[] SEASON_2 = {3, 4, 5};
    private static final int[] SEASON_3 = {6, 7, 8};
    private static final int[] SEASON_4 = {9, 10, 11};


    public enum DATE_PATTERN {

        /**
         * yyyyMMdd
         */
        yyyyMMdd("yyyyMMdd", "^\\d{2,4}\\d{1,2}\\d{1,2}$"),

        /**
         * yyyy/MM
         */
        yyyy_MM("yyyy/MM", "^\\d{2,4}/\\d{1,2}$"),

        /**
         * yyyy-MM
         */
        yyyy_MM2("yyyy-MM", "^\\d{2,4}-\\d{1,2}$"),

        /**
         * yyyy/MM/dd
         */
        yyyy_MM_dd("yyyy/MM/dd", "^\\d{2,4}/\\d{1,2}/\\d{1,2}$"),

        /**
         * yyyy-MM-dd
         */
        yyyy_MM_dd2("yyyy-MM-dd", "^\\d{2,4}-\\d{1,2}-\\d{1,2}$"),

        /**
         * yyyy/MM/dd HH:mm
         */
        yyyy_MM_dd_HH_mm("yyyy/MM/dd HH:mm", "^\\d{2,4}/\\d{1,2}/\\d{1,2}\\s.{1,2}\\d{1,2}:\\d{1,2}$"),

        /**
         * yyyy-MM-dd HH:mm
         */
        yyyy_MM_dd_HH_mm2("yyyy-MM-dd HH:mm", "^\\d{2,4}-\\d{1,2}-\\d{1,2}\\s.{1,2}\\d{1,2}:\\d{1,2}$"),

        /**
         * yyyy/MM/dd HH:mm:ss
         */
        yyyy_MM_dd_HH_mm_ss("yyyy/MM/dd HH:mm:ss", "^\\d{2,4}/\\d{1,2}/\\d{1,2}\\s.{1,2}\\d{1,2}:\\d{1,2}:\\d{1,2}$"),

        /**
         * yyyy-MM-dd HH:mm:ss
         */
        yyyy_MM_dd_HH_mm_ss2("yyyy-MM-dd HH:mm:ss", "^\\d{2,4}-\\d{1,2}-\\d{1,2}\\s.{1,2}\\d{1,2}:\\d{1,2}:\\d{1,2}$"),

        /**
         * yyyy/MM/dd HH:mm:ss.S
         */
        yyyy_MM_dd_HH_mm_ss_S("yyyy/MM/dd HH:mm:ss.S", "^\\d{2,4}/\\d{1,2}/\\d{1,2}\\s.{1,2}\\d{1,2}:\\d{1,2}:\\d{1," +
                "2}\\.\\d{1,}$"),

        /**
         * yyyy-MM-dd HH:mm:ss.S
         */
        yyyy_MM_dd_HH_mm_ss_S2("yyyy-MM-dd HH:mm:ss.S", "^\\d{2,4}-\\d{1,2}-\\d{1,2}\\s.{1,2}\\d{1,2}:\\d{1,2}:\\d{1," +
                "2}\\.\\d{1,}$");

        private String value;

        private String pattern;

        private DATE_PATTERN(String value, String pattern) {
            this.value = value;
            this.pattern = pattern;
        }

        /**
         * 根据样本获取模式
         *
         * @param date
         * @return
         */
        public static DATE_PATTERN getPatternBySample(String date) {

            if (date != null) {

                date = date.trim();

                for (DATE_PATTERN value : DATE_PATTERN.values()) {

                    if (date.matches(value.pattern)) {
                        return value;
                    }
                }
            }

            throw new ServiceException("日期为空或是不支持的样本格式：" + date);
        }

        @Override
        public String toString() {
            return value;
        }
    }

    /**
     * 日期比较
     *
     * @param date1
     * @param date2
     * @return 如果 date1 > date2，则返回 1;如果 date1 = date2,则返回 0;如果 date1 < date2，则返回 -1
     */
    public static int compareDate(Date date1, Date date2) {

        if (date1.getTime() > date2.getTime()) {

            return 1;
        } else if (date1.getTime() == date2.getTime()) {

            return 0;
        } else {

            return -1;
        }
    }

    /**
     * 计算 minute 分钟后的时间
     *
     * @param date
     * @param minute
     * @return
     */
    public static Date addMinute(Date date, int minute) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MINUTE, minute);
        return calendar.getTime();
    }

    /**
     * 根据指定模式解析时间字符串为 date 对象并返回
     *
     * @param date
     * @param pattern
     * @return
     */
    public static Date str2Date(String date, DATE_PATTERN pattern) {
        try {
            DateFormat df = new SimpleDateFormat(pattern.toString());
            return df.parse(date);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 根据yyyyMMddHHmmss模式解析时间字符串为 date 对象并返回
     *
     * @param date
     * @return
     */
    public static Date str2Date(String date) {
        if (StringUtils.isBlank(date)) {
            return null;
        }
        try {
            return GAPLESS_DATE_FORMATTER.parse(date);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static String date2Str(Date date) {
        return date2Str(date, DATE_PATTERN.yyyy_MM_dd_HH_mm_ss2);
    }

    /**
     * 时间转换成 Date 类型
     *
     * @param date
     * @param pattern
     * @return
     */
    public static String date2Str(Date date, DATE_PATTERN pattern) {
        SimpleDateFormat sdf = new SimpleDateFormat(pattern.toString());
        if (date != null) {
            return sdf.format(date);
        }
        return "";
    }

    /**
     * 日期比较
     *
     * @param date1
     * @param date2
     * @return 如果 date1 > date2，则返回 1;如果 date1 = date2,则返回 0;如果 date1 < date2，则返回 -1
     */
    public static int compareDate(String date1, DATE_PATTERN date1Pattern, String date2, DATE_PATTERN date2Pattern) {

        Date _date1 = parseDate(date1, date1Pattern);
        Date _date2 = parseDate(date2, date2Pattern);

        return compareDate(_date1, _date2);
    }

    /**
     * 根据指定的模式，将 java.util.Date 转换为 java.sql.Date
     *
     * @param date
     * @param datePattern
     * @return
     */
    public static java.sql.Date toSqlDate(String date, DATE_PATTERN datePattern) {

        return new java.sql.Date(parseDate(date, datePattern).getTime());
    }

    /**
     * 根据指定的模式，将 java.util.Date 转换为 java.sql.Timestamp
     *
     * @param date
     * @param datePattern
     * @return
     */
    public static Timestamp toTimestamp(String date, DATE_PATTERN datePattern) {

        return new Timestamp(parseDate(date, datePattern).getTime());
    }

    /**
     * 解析任意受支持格式的时间
     *
     * @param date
     * @return
     */
    @SuppressWarnings("deprecation")
    public static Date parseDate(String date) {

        if (date == null) {
            return null;
        }

        date = date.trim();
        if (date.indexOf("中国标准时间") != -1 || date.indexOf("CST") != -1) {
            return new Date(Date.parse(date));
        }

        return parseDate(date, getPatternBySample(date));
    }

    /**
     * 根据指定模式解析时间字符串为 date 对象并返回
     *
     * @param date    date字符串
     * @param pattern 模式
     * @return
     */
    public static Date parseDate(String date, DATE_PATTERN pattern) {

        try {

            DateFormat df = new SimpleDateFormat(pattern.toString());
            return df.parse(date);

        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

    /**
     * 格式化时间
     * <br/>
     * 按照指定模式格式化时间字符串
     *
     * @param srcDateStr        源日期
     * @param srcDatePattern    源日期模式
     * @param targetDatePattern 目标日期模式
     * @return
     */
    public static String formatDate(String srcDateStr, DATE_PATTERN srcDatePattern, DATE_PATTERN targetDatePattern) {

        try {

            DateFormat df = new SimpleDateFormat(srcDatePattern.toString());
            Date srcDate = df.parse(srcDateStr);

            DateFormat df2 = new SimpleDateFormat(targetDatePattern.toString());
            String targetDateStr = df2.format(srcDate);

            return targetDateStr;

        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

    /**
     * 格式化时间
     *
     * @param date
     * @param datePattern 模式
     * @return
     */
    public static String formatDate(Date date, DATE_PATTERN datePattern) {

        DateFormat df = new SimpleDateFormat(datePattern.toString());
        return df.format(date);
    }

    /**
     * 根据日期样品获得其模式
     *
     * @param sample
     * @return
     */
    public static DATE_PATTERN getPatternBySample(String sample) {

        return DATE_PATTERN.getPatternBySample(sample);
    }

    /**
     * 计算时间
     *
     * @param date 时间（年月日）
     * @param type 类型（1:加、2:减）
     * @param num  数值(天数)
     * @return
     */
    public static Date calculateTime(Date date, int type, int num) {
        long time = date.getTime();

        long tempTime = num * 1 * 24 * 60 * 60 * 1000;
        if (1 == type) {
            time += tempTime;
        } else if (2 == type) {
            time -= tempTime;
        } else {
            throw new ServiceException("传参错误");
        }
        return new Date(time);
    }


    /**
     * 字符串转为　yyyy-MM-dd HH:mm:ss
     *
     * @param str
     * @return
     */
    public static Date parse(String str) {
        try {
            return DATE_FORMATTER.parse(str);
        } catch (ParseException e) {
            //logger.error("日期转换失败：{}", str);
            throw new RuntimeException(e);
        }
    }

    /**
     * 字符串转为　yyyy-MM-dd
     *
     * @param str
     * @return
     */
    public static Date baseParse_1(String str) {
        try {
            return BASE_DATE_FORMATTER_1.parse(str);
        } catch (ParseException e) {
            //logger.error("日期转换失败：{}", str);
            throw new RuntimeException(e);
        }
    }

    /**
     * 字符串转为　yyyy-MM-dd
     *
     * @param str
     * @return
     */
    public static Date baseParse(String str) {
        try {
            return BASE_DATE_FORMATTER.parse(str);
        } catch (ParseException e) {
            //logger.error("日期转换失败：{}", str);
            throw new RuntimeException(e);
        }
    }


    /**
     * 字符串转为　yyyy-MM-dd
     *
     * @param date
     * @return
     */
    public static Date baseFormatParse(Date date) {
        try {
            return BASE_DATE_FORMATTER.parse(DATE_FORMATTER.format(date));
        } catch (ParseException e) {
            //logger.error("日期转换失败：{}", str);
            throw new RuntimeException(e);
        }
    }

    /**
     * 字符串转为　HH-mm
     *
     * @param str
     * @return
     */
    public static Date hourMinuteParse(String str) {
        try {
            return HOUR_MINUTE_DATE_FORMATTER.parse(str);
        } catch (ParseException e) {
            //logger.error("日期转换失败：{}", str);
            throw new RuntimeException(e);
        }
    }

    /**
     * 字符串转为　HH-mm
     *
     * @param date
     * @return
     */
    public static Date hourMinuteFormatParse(Date date) {
        try {
            return HOUR_MINUTE_DATE_FORMATTER.parse(HOUR_MINUTE_DATE_FORMATTER.format(date));
        } catch (ParseException e) {
            //logger.error("日期转换失败：{}", str);
            throw new RuntimeException(e);
        }
    }

    /**
     * 字符串转为　yyyy-MM
     *
     * @param str
     * @return
     */
    public static Date monthPase(String str) {
        try {
            return MONTH_FORMATTER.parse(str);
        } catch (ParseException e) {
            //logger.error("日期转换失败：{}", str);
            throw new RuntimeException(e);
        }
    }

    /**
     * @param date
     * @return
     */
    public static String monthFormat(Date date) {
        return MONTH_FORMATTER.format(date);
    }

    /**
     * 　LocalDateTime　格式化为字符串
     *
     * @param date
     * @return
     */
    public static String format(Date date) {
        if (date == null) {
            return "";
        }
        return DATE_FORMATTER.format(date);
    }

    /**
     * 格式化为字符串到分钟
     *
     * @param date
     * @return
     */
    public static String formatToString(Date date, String pattern) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
        return simpleDateFormat.format(date);
    }

    /**
     * 　LocalDateTime　格式化为字符串
     *
     * @param date
     * @return
     */
    public static String baseFormat(Date date) {
        return BASE_DATE_FORMATTER.format(date);
    }

    public static String baseFormat(Date date, String formatStr) {
        return FastDateFormat.getInstance(formatStr).format(date);
    }

    public static String HourMinuteFormat(Date date) {
        return HOUR_MINUTE_DATE_FORMATTER.format(date);
    }


    public static Date YearHourMinuteFormat(String date) {
        try {
            return HOUR_MINUTE_FORMATTER.parse(date);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }


    public static String YearHourMinuteFormat(Date date) {
        return HOUR_MINUTE_FORMATTER.format(date);
    }

    /**
     * 获取当前时间戳，单位秒
     *
     * @return
     */
    public static String getCurrentTimeSecond() {
        Long timeMillis = System.currentTimeMillis() / 1000;
        String timeMillisStr = timeMillis.toString();
        return timeMillisStr;
    }

    /**
     * 获取当前时间戳，单位毫秒
     *
     * @return
     */
    public static long getCurrentTimestampMs() {
        return System.currentTimeMillis();
    }

    /**
     * description: <br>
     * 〈yyyyMMddHHmmss〉
     *
     * @param date
     * @Author:qinjp
     * @Date: 17-11-10 上午9:33
     * @return: java.lang.String
     */
    public static String getGaplessTime(Date date) {
        return GAPLESS_DATE_FORMATTER.format(date);
    }

    public static String addGaplessTime(Date date, int minute) {
        return GAPLESS_DATE_FORMATTER.format(addMinute(date, minute));
    }

    public static Date passToDate(String str) {

        try {
            return GAPLESS_DATE_FORMATTER.parse(str);
        } catch (ParseException e) {
            //logger.error("日期转换失败：{" + e + "}", str);
            throw new RuntimeException(e);
        }
    }

    /**
     * description: <br>
     * 〈获取17位时间戳〉
     *
     * @param date
     * @Author:qinjp
     * @Date: 17-11-10 上午9:59
     * @return: java.lang.String
     */
    public static String getMillisTime(Date date) {

        return MILLIS_DATE_FORMATTER.format(date);
    }

    public static String getTimestamp(String format) {
        Date date = new Date();
        DateFormat dateFormat = new SimpleDateFormat(format);
        String timestamp = dateFormat.format(date);
        return timestamp;
    }

    public static Date addMinuteDate(Date date, int minute) {

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MINUTE, minute);
        Date timeStamp = calendar.getTime();
        return timeStamp;
    }

    public static Date addSecondDate(Date date, int second) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.SECOND, second);
        Date timeStamp = calendar.getTime();
        return timeStamp;
    }

    public static Date minusMinuteDate(Date date, int minute) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MINUTE, -minute);
        Date timeStamp = calendar.getTime();
        return timeStamp;
    }

    public static Date addHoursDate(Date date, int hours) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.HOUR_OF_DAY, hours);
        Date timestamp = calendar.getTime();
        return timestamp;

    }

    public static Date minusHoursDate(Date date, int hours) {

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.HOUR_OF_DAY, -hours);

        Date timestamp = calendar.getTime();
        return timestamp;
    }

    public static Date addYearDate(Date date, int years) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.YEAR, years);
        Date timestamp = calendar.getTime();
        return timestamp;

    }

    public static Date addDayDate(Date date, int days) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_MONTH, days);
        Date timestamp = calendar.getTime();
        return timestamp;

    }

    public static Date addMonthDate(Date date, int month) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, month);
        Date timestamp = calendar.getTime();
        return timestamp;
    }

    public static Date minusDayDate(Date date, int days) {

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_MONTH, -days);

        Date timestamp = calendar.getTime();
        return timestamp;
    }

    /**
     * 是否几个月内
     *
     * @param date
     * @return
     */
    public static Boolean inFewMonthsDate(Date date, int month, int days) {
        Date temp = new Date();
        Calendar start = Calendar.getInstance();
        start.setTime(temp);
        start.set(Calendar.HOUR_OF_DAY, 0);
        start.set(Calendar.MINUTE, 0);
        start.set(Calendar.SECOND, 0);
        start.set(Calendar.MILLISECOND, 0);
        start.add(Calendar.MONTH, -month);
        start.add(Calendar.DAY_OF_MONTH, days);
        return date.after(start.getTime()) && date.before(new Date());
    }

    /**
     * 几个月前的时间
     *
     * @param date
     * @param days
     * @return
     */
    public static String getFewMonthsAgoDate(Date date, int month, int days) {
        Calendar start = Calendar.getInstance();
        start.setTime(date);
        start.set(Calendar.HOUR_OF_DAY, 0);
        start.set(Calendar.MINUTE, 0);
        start.set(Calendar.SECOND, 0);
        start.set(Calendar.MILLISECOND, 0);
        start.add(Calendar.MONTH, -month);
        start.add(Calendar.DAY_OF_MONTH, days);
        return DateUtil.formatDate(start.getTime(), DateUtil.DATE_PATTERN.yyyy_MM_dd_HH_mm_ss2);
    }


    /**
     * 根据身份证计算年龄
     *
     * @param s
     * @return
     */
    public static String toAge(String s, Date now) {
        if (StringUtils.isBlank(s)) {
            return "";
        }
        int leh = s.length();
        if (leh != 18 && leh != 15) {
            return "";
        }

        try {
            String dates = null;
            if (leh == 18) {
                dates = s.substring(6, 10) + "-" + s.substring(10, 12) + "-" + s.substring(12, 14);
            } else {
                dates = "19" + s.substring(6, 8) + "-" + s.substring(8, 10) + "-"
                        + s.substring(10, 12);
            }
            Date birthday = baseParse(dates);
            int age = getAgeByBirthday(birthday, now);
            return age + "";
        } catch (Exception e) {
            //logger.error("身份证计算年龄异常", e);
            e.printStackTrace();
            return "";
        }
    }


    /**
     * 根据出生日期计算年龄
     *
     * @param now
     * @param birthday
     * @return
     */
    public static int getAgeByBirthday(Date birthday, Date now) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(now);
        if (cal.before(birthday)) {
            throw new IllegalArgumentException("The birthDay is before Now.It's unbelievable!");
        }

        int yearNow = cal.get(Calendar.YEAR);
        int monthNow = cal.get(Calendar.MONTH) + 1;
        int dayOfMonthNow = cal.get(Calendar.DAY_OF_MONTH);

        cal.setTime(birthday);
        int yearBirth = cal.get(Calendar.YEAR);
        int monthBirth = cal.get(Calendar.MONTH) + 1;
        int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH);

        int age = yearNow - yearBirth;
        if (monthNow <= monthBirth) {
            if (monthNow == monthBirth) {
                if (dayOfMonthNow < dayOfMonthBirth) {
                    age--;
                }
            } else {
                age--;
            }
        }
        return age;
    }

    public static int getAgeYear(Date birthday) {
        long mills = System.currentTimeMillis() - birthday.getTime();
        double d = mills * 1.0 / new Double(1000 * 60 * 60 * 24 * 365L).longValue();
        return new Double(d).intValue();
    }


    /**
     * 获取日期的年份
     *
     * @param date
     * @return
     */
    public static int getYear(Date date) {
        Calendar instance = Calendar.getInstance();
        instance.setTime(date);
        return instance.get(Calendar.YEAR);
    }

    /**
     * 获取日期的月份
     *
     * @param date
     * @return
     */
    public static int getMonth(Date date) {
        Calendar instance = Calendar.getInstance();
        instance.setTime(date);
        return instance.get(Calendar.MONTH) + 1;
    }

    /**
     * 获取日期的每月的第几日
     *
     * @param date
     * @return
     */
    public static int getDay(Date date) {
        Calendar instance = Calendar.getInstance();
        instance.setTime(date);
        return instance.get(Calendar.DAY_OF_MONTH);
    }

    /**
     * 根据日期获取当前小时
     *
     * @param date
     * @return
     */
    public static int getHours(Date date) {
        Calendar instance = Calendar.getInstance();
        instance.setTime(date);
        return instance.get(Calendar.HOUR_OF_DAY);
    }

    /**
     * 根据日期获取当前小时
     *
     * @param date
     * @return
     */
    public static int getMinutes(Date date) {
        Calendar instance = Calendar.getInstance();
        instance.setTime(date);
        return instance.get(Calendar.MINUTE);
    }

    /**
     * 通过日期转换成字符串日期
     *
     * @param date
     * @return
     */
    public static String transforDate(Date date) {
        Calendar instance = Calendar.getInstance();
        instance.setTime(date);
        int month = instance.get(Calendar.MONTH);
        int day = instance.get(Calendar.DAY_OF_MONTH);
        int hour = instance.get(Calendar.HOUR_OF_DAY);
        int minute = instance.get(Calendar.MINUTE);
        return month + "月" + day + "日  " + hour + "点" + minute + "分";
    }


    public static final int _DIFF_DAY = 1;
    public static final int _DIFF_HOUR = 2;
    public static final int _DIFF_MIN = 3;

    /**
     * 根据类型计算开始结束时间之间差值
     *
     * @param endDate
     * @param startDate
     * @param type
     * @return
     */
    public static long getDiffTime(Date endDate, Date startDate, int type) {

        if (null == endDate || null == startDate || startDate.after(endDate)) {
            return 0;
        }


        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        // long ns = 1000;
        // 获得两个时间的毫秒时间差异
        long diff = endDate.getTime() - startDate.getTime();
        // 计算差多少天
        if (_DIFF_DAY == type) {
            return diff / nd;
        }
        // 计算差多少小时
        if (_DIFF_HOUR == type) {
            return diff / nh;
        }
        // 计算差多少分钟
        if (_DIFF_MIN == type) {
            return diff / nm;
        }

        return 0;
    }

    /**
     * 获取当前时间到零点的毫秒数
     *
     * @return
     */
    public static long getTomorrowZeroSeconds() {
        long current = System.currentTimeMillis();// 当前时间毫秒数
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        long tomorrowzero = calendar.getTimeInMillis();
        return tomorrowzero - current;
    }

    /**
     * 获取年龄
     *
     * @param birth
     * @return
     */
    public static String getAge(Date birth) {
        if (birth == null) {
            return null;
        }
        long day = new Long((System.currentTimeMillis() - birth.getTime()) / ((1000 * 60 * 60) * 24)).intValue();
        int year = new Long(day / 365).intValue();
        int month = new Long(day / 30).intValue();
        return year == 0 ? (month == 0 ? day + "天" : month + "个月") : year + "岁";
    }


    /**
     * 获取一天的开始时间
     *
     * @param date
     * @return
     */
    public static Date getHourStart(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }

    /**
     * 获取一天的结束时间
     *
     * @param date
     * @return
     */
    public static Date getHourEnd(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        cal.set(Calendar.MILLISECOND, 999);
        return cal.getTime();
    }

    /**
     * 获取一天的开始时间
     *
     * @param date
     * @return
     */
    public static Date getDayStart(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }

    /**
     * 获取一天的结束时间
     *
     * @param date
     * @return
     */
    public static Date getDayEnd(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        cal.set(Calendar.MILLISECOND, 999);
        return cal.getTime();
    }

    /**
     * 获取一周的开始时间和结束时间
     */

    public static Date getWeekStart(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }

    /**
     * 获取一周的结束时间
     */

    public static Date getWeekEnd(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY);
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        cal.set(Calendar.MILLISECOND, 999);
        return cal.getTime();
    }

    /**
     * 获取一月的开始
     */

    public static Date getMonthStart(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.DAY_OF_MONTH, 1);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }

    /**
     * 获取一月的结束
     */

    public static Date getMonthEnd(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        cal.set(Calendar.MILLISECOND, 999);
        return cal.getTime();
    }

    public static Date getYearStart(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.MONTH, Calendar.JANUARY);
        cal.set(Calendar.DAY_OF_MONTH, 1);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }

    public static Date getYearEnd(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.MONTH, Calendar.DECEMBER);
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        cal.set(Calendar.MILLISECOND, 999);
        return cal.getTime();
    }

    /**
     * 通过月份获取相应季度的开始时间
     *
     * @param month
     * @return
     */
    public static Date getSeasonStart(int month) {
        if (month < 0 || month > 11) {
            return null;
        }
        Calendar cal = Calendar.getInstance();
        int start = -1;
        if (month <= 2) {
            start = 0;
        }

        if (month <= 5) {
            start = 3;
        }

        if (month <= 8) {
            start = 6;
        } else {
            start = 9;
        }
        cal.set(Calendar.MONTH, start);
        return getMonthStart(cal.getTime());
    }

    /**
     * 通过月份获取相应季度的最后时间
     *
     * @param month
     * @return
     */
    public static Date getSeasonEnd(int month) {
        if (month < 0 || month > 11) {
            return null;
        }
        Calendar cal = Calendar.getInstance();
        int start = -1;
        if (month <= 2) {
            start = 2;
        }

        if (month <= 5) {
            start = 5;
        }

        if (month <= 8) {
            start = 8;
        } else {
            start = 11;
        }
        cal.set(Calendar.MONTH, start);
        return getMonthEnd(cal.getTime());
    }

    /**
     * 通过月份获取相应季度的最后时间
     *
     * @param month
     * @return
     */
    public static int[] getSeason(int month) {
        if (month < 0 || month > 11) {
            return null;
        }
        Calendar cal = Calendar.getInstance();
        int start = -1;
        if (month <= 2) {
            return SEASON_1;
        }

        if (month <= 5) {
            return SEASON_2;
        }

        if (month <= 8) {
            return SEASON_3;
        } else {
            return SEASON_4;
        }
    }

    /**
     * 获取一分钟的开始时间
     *
     * @param date
     * @return
     */
    public static Date getMinStart(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }

    /**
     * 获取一分钟的结束时间
     *
     * @param date
     * @return
     */
    public static Date getMinEnd(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.SECOND, 59);
        cal.set(Calendar.MILLISECOND, 999);
        return cal.getTime();
    }

    /**
     * 根据毫秒数获取时长
     *
     * @param mss
     * @return
     */
    public static String formatDuring(long mss) {
        if (mss == 0) {
            return "";
        }
        long days = mss / (1000 * 60 * 60 * 24);
        long hours = (mss % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60);
        long minutes = (mss % (1000 * 60 * 60)) / (1000 * 60);
        long seconds = (mss % (1000 * 60)) / 1000;
        StringBuilder duration = new StringBuilder();
        if (days != 0) {
            duration.append(days + "天");
        }
        if (hours != 0) {
            duration.append(hours + "时");
        }
        if (minutes != 0) {
            duration.append(minutes + "分");
        }
        if (seconds != 0) {
            duration.append(seconds + "秒");
        }
        return duration.toString();
    }

    /**
     * 根据日期获取星期（）
     *
     * @param datetime
     * @return
     */
    public static Integer dateToWeek(String datetime) {
        SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd");
        Integer[] weekDays = {0, 1, 2, 3, 4, 5, 6};
        Calendar cal = Calendar.getInstance(); // 获得一个日历
        Date datet = null;
        try {
            datet = f.parse(datetime);
            cal.setTime(datet);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        int w = cal.get(Calendar.DAY_OF_WEEK) - 1; // 指示一个星期中的某天。
        if (w < 0) {
            w = 0;
        }
        return weekDays[w];
    }

    /**
     * 判断两个时间段是否存在交集
     *
     * @param startdate1
     * @param enddate1
     * @param startdate2
     * @param enddate2
     * @return
     */
    public static Map<String, Date> isOverlap(String startdate1, String enddate1, String startdate2, String enddate2) {
        SimpleDateFormat format = new SimpleDateFormat("HH:mm");
        Date leftStartDate = null;
        Date leftEndDate = null;
        Date rightStartDate = null;
        Date rightEndDate = null;
        try {
            leftStartDate = format.parse(startdate1);
            leftEndDate = format.parse(enddate1);
            rightStartDate = format.parse(startdate2);
            rightEndDate = format.parse(enddate2);
        } catch (ParseException e) {
            return null;
        }
        Map<String, Date> map = new HashMap<>();

        if (leftEndDate.getTime() <= rightStartDate.getTime()
                || leftStartDate.getTime() >= rightEndDate.getTime()) {
            return null;
        }
        long[] longTime = {leftStartDate.getTime(), leftEndDate.getTime(),
                rightStartDate.getTime(), rightEndDate.getTime()};
        Arrays.sort(longTime); //从小到大排序，取第二、第三计算
        map.put("startTime", new Date(longTime[1]));
        map.put("endTime", new Date(longTime[2]));

        return map;
    }

    /**
     * 格式化日期
     *
     * @param date
     * @return
     */
    public static Date formatDate(Date date) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            String dateStr = sdf.format(date);
            date = sdf.parse(dateStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return date;
    }

    /**
     * 判断两个日期是否相等
     *
     * @param d1
     * @param d2
     * @return
     */
    public static boolean sameDate(Date d1, Date d2) {
        if (null == d1 || null == d2) {
            return false;
        }
        Calendar cal1 = Calendar.getInstance();
        cal1.setTime(d1);
        /*cal1.set(Calendar.HOUR_OF_DAY, 0);
        cal1.set(Calendar.MINUTE, 0);
        cal1.set(Calendar.SECOND, 0);
        cal1.set(Calendar.MILLISECOND, 0);*/
        Calendar cal2 = Calendar.getInstance();
        cal2.setTime(d2);
        /*cal2.set(Calendar.HOUR_OF_DAY, 0);
        cal2.set(Calendar.MINUTE, 0);
        cal2.set(Calendar.SECOND, 0);
        cal2.set(Calendar.MILLISECOND, 0);*/
        return cal1.getTime().equals(cal2.getTime());
    }

    /**
     * 根据当前时间，添加或减去指定的时间量。例如，要从当前日历时间减去 5 天，可以通过调用以下方法做到这一点：
     * add(Calendar.DAY_OF_MONTH, -5)。
     *
     * @param date 指定时间
     * @param num  为时间添加或减去的时间天数
     * @return
     */
    public static Date getBeforeOrAfterDate(Date date, int num) {
        Calendar calendar = Calendar.getInstance();//获取日历
        calendar.setTime(date);//当date的值是当前时间，则可以不用写这段代码。
        calendar.add(Calendar.DATE, num);
        Date d = calendar.getTime();//把日历转换为Date
        return d;
    }


    /* 获取过去或者未来 任意天内的日期数组
     * @param intervals      intervals天内
     * @return              日期数组
     */
    public static ArrayList<String> getFutureDayList(int intervals) {
        //ArrayList<String> pastDaysList = new ArrayList<>();
        ArrayList<String> fetureDaysList = new ArrayList<>();
        for (int i = 0; i < intervals; i++) {
            //pastDaysList.add(getPastDate(i));
            fetureDaysList.add(getFetureDate(i));
        }
        return fetureDaysList;
    }

    /**
     * 获取未来 第 past 天的日期
     *
     * @param past
     * @return
     */
    public static String getFetureDate(int past) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_YEAR, calendar.get(Calendar.DAY_OF_YEAR) + past);
        Date today = calendar.getTime();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String result = format.format(today);
        return result;
    }


    /**
     * 使用 Map 按 Key 进行排序
     *
     * @param oriMap 排序 Map 集合
     * @param isRise 是否按照升序排序
     */
    public static Map<String, String> sortMapByKey(Map<String, String> oriMap, final boolean isRise) {
        if (oriMap == null || oriMap.isEmpty()) {
            return null;
        }

        Map<String, String> sortMap = new TreeMap<>(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                if (isRise) {
                    // 升序排序
                    return o1.compareTo(o2);
                } else {
                    // 降序排序
                    return o2.compareTo(o1);
                }
            }
        });
        sortMap.putAll(oriMap);
        return sortMap;
    }


    /**
     * 获取当前日期是星期几<br>
     *
     * @param date
     * @return 当前日期是星期几
     */
    public static Integer getWeekOfDate(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        Integer week = cal.get(Calendar.DAY_OF_WEEK) - 1;
        if (week < 0) {
            week = 0;
        }
        return week;
    }

    /**
     * 当日的指定小时的时间
     */

    @SuppressWarnings("Duplicates")
    public static Date getDateByHourAndMin(int hour, int min) {
        return getDate(new Date(), hour, min);
    }

    /**
     * @param date
     * @param hour
     * @param min
     * @return
     */
    public static Date getDate(Date date, int hour, int min) {
        Calendar instance = Calendar.getInstance();
        instance.setTime(date);
        instance.set(Calendar.HOUR_OF_DAY, hour);
        instance.set(Calendar.MINUTE, min);
        instance.set(Calendar.SECOND, 0);
        instance.set(Calendar.MILLISECOND, 0);
        return instance.getTime();
    }

    /**
     * 获取两个时间的最小值
     *
     * @param d1
     * @param d2
     * @return
     */
    public static Date getMinDate(Date d1, Date d2) {
        return d1.before(d2) ? d1 : d2;
    }

    /**
     * 获取两个时间的最大值
     *
     * @param d1
     * @param d2
     * @return
     */
    public static Date getMaxDate(Date d1, Date d2) {
        return d1.before(d2) ? d2 : d1;
    }

    /**
     * 格式 化时间
     *
     * @param time long
     * @return String
     */
    public static String formatDate(long time) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdf.format(new Date(Long.parseLong(String.valueOf(time))));
    }

    /**
     * 计算年龄
     *
     * @param birthday Date
     * @return Age
     */
    public static Age getAgeAndAgeUnit(Date birthday) {
        Date now = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(now);

        Calendar birth = Calendar.getInstance();
        birth.setTime(birthday);
        Age age = new Age();
        if (calendar.get(Calendar.YEAR) == birth.get(Calendar.YEAR)) {
            if (calendar.get(Calendar.MONTH) > birth.get(Calendar.MONTH)) {
                age.setAge(calendar.get(Calendar.MONTH) - birth.get(Calendar.MONTH) + 1);
                age.setAgeUnit("月");
            } else if (calendar.get(Calendar.MONTH) == birth.get(Calendar.MONTH)) {
                age.setAge(calendar.get(Calendar.DAY_OF_MONTH) - birth.get(Calendar.DAY_OF_MONTH) + 1);
                age.setAgeUnit("天");
            }
        } else {
            age.setAge(getAgeByBirthday(birthday, now));
            age.setAgeUnit("岁");
        }
        return age;
    }

    @Setter
    @Getter
    public static class Age {
        private Integer age;
        private String ageUnit;
    }
}
